package com.zbkj.crmeb.order.pprocess;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

import com.utils.HttpUtils;
import com.utils.monitor.DingMsgEnum;
import com.utils.monitor.DingTalkMsgUtil;
import com.zbkj.crmeb.chant.request.PurchaseProductRequest;
import com.zbkj.crmeb.enums.RoleEnum;
import io.netty.util.concurrent.CompleteFuture;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.constants.Constants;
import com.constants.WeChatConstants;
import com.crmeb.core.exception.CrmebException;
import com.utils.adapay.degree.HttpSendResult;
import com.utils.adapay.degree.SignTool;
import com.utils.adapay.degree.SimpleHttpsClient;
import com.zbkj.crmeb.finance.model.UserRecharge;
import com.zbkj.crmeb.finance.service.UserRechargeService;
import com.zbkj.crmeb.finance.service.process.IRechargeOrderProcess;
import com.zbkj.crmeb.front.request.OrderCreateRequest;
import com.zbkj.crmeb.front.request.UserRechargeRequest;
import com.zbkj.crmeb.front.response.OrderPayResponse;
import com.zbkj.crmeb.merchant.api.request.BuyMemberRequest;
import com.zbkj.crmeb.store.model.StoreOrder;
import com.zbkj.crmeb.store.model.StoreOrderInfo;
import com.zbkj.crmeb.store.request.StoreOrderRefundRequest;
import com.zbkj.crmeb.store.service.StoreOrderInfoService;
import com.zbkj.crmeb.store.service.StoreOrderService;
import com.zbkj.crmeb.store.vo.StoreOrderInfoVo;
import com.zbkj.crmeb.system.service.SystemConfigService;
import com.zbkj.crmeb.system.service.SystemGroupDataService;
import com.zbkj.crmeb.system.vo.SystemGroupDataRechargeConfigVo;
import com.zbkj.crmeb.user.service.UserService;

import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * 汇付聚合支付
 * @author daigb
 * @date:  2022-07-18 11:31
 */
@Slf4j
@Service("adapayDegreePayOrderProcess")
public class AdapayDegreePayOrderProcess extends AbstractOrangePayOrderProcess implements IRechargeOrderProcess {
    @Autowired
    private SystemConfigService systemConfigService;
    @Autowired
    private SimpleHttpsClient simpleHttpsClient;
    @Autowired
    private UserService userService;
    @Autowired
    private SystemGroupDataService systemGroupDataService;
    @Autowired
    private UserRechargeService userRechargeService;
    @Autowired
    private StoreOrderService storeOrderService;
    @Autowired
    private StoreOrderInfoService storeOrderInfoService;
    
    @Value("${adapay.degree.payUrl}")
    private String payUrl;
    @Value("${adapay.degree.refundUrl}")
    private String refundUrl;
    @Value("${adapay.degree.customsUrl}")
    private String customsUrl;
    @Value("${adapay.degree.transDivUrl}")
    private String transDivUrl;
    @Value("${adapay.degree.rollbackUrl}")
    private String rollbackUrl;
    @Value("${adapay.degree.password}")
	private String password;
    @Value("${adapay.degree.alias}")
	private String alias;
	@Value("${adapay.suyun.merIds}")
	private List<Integer> syMerIds;
	@Value("${adapay.chengpin.merIds}")
	private List<Integer> cpMerIds;
	@Value("${adapay.chutai.merIds}")
	private List<Integer> ctMerIds;
	@Value("${adapay.maisi.merIds}")
	private List<Integer> msMerIds;
	@Value(("${adapay.wenmiaojie.merIds}"))
	private List<Integer> wmjMerIds;
	@Value("${productType.merchantId}")
	private Integer productTypeMerchantId;
    
    private SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
    
    public static final String PATH = "/data/cert/adapay/";
    //public static final String PATH = "D://adapay/";
    public static final String CHARSET = "1";
    public static final String VERSION = "3.0";
    public static final String LANGUAGE = "1";
    public static final String SIGN_TYPE = "4";

    // 诚品
    public static final String MERCHANT_ACCT_ID_CP = "10122070636";
    public static final String TERMINAL_ID_CP = "CPRS001";
    public static final String TERMINAL_CUSTOMS_ID_CP = "CPRS006";
    
    // 速云
    public static final String MERCHANT_ACCT_ID_SY = "10122080652";
    public static final String TERMINAL_ID_SY = "SYGYL001";
//    public static final String TERMINAL_CUSTOMS_ID_SY = "SYGYL007";

	public static final String TERMINAL_CUSTOMS_ID_SY = "SYGYL008";
	public static final String TERMINAL_CUSTOMS_ID_WMJ = "SYGYL006";

	// 初苔
	public static final String MERCHANT_ACCT_ID_CT = "10123020695";
	public static final String TERMINAL_ID_CT = "WZCT001";
	public static final String TERMINAL_CUSTOMS_ID_CT = "WZCT002";

	// 麦丝
	public static final String MERCHANT_ACCT_ID_MS = "10123050712";
	public static final String TERMINAL_ID_MS = "MSMJ001";
	public static final String TERMINAL_CUSTOMS_ID_MS = "MSMJ002";
    
    public static final String CURRENCY = "CNY";
	public static final String SIGNATUREPARAMS = "competCustom,customCode,customVersion,dealId,declareId,"
			+ "decResult,ecpDomainName,ecpShortName,errorCode,errorMsg,freightAmt,goodsAmt,iaqInstCode,"
			+ "merchantAcctId,merCustomCode,merCustomName,offsetAmt,orderAmt,orderCurrency,orderId,payerIdType,"
			+ "payerIdNumber,payerName,taxAmt,terminalId,bizType,version";
    
    /**
     * 创建订单
     */
    public OrderPayResponse creatPayOrder(String key, OrderCreateRequest orderRequest, String ip) {
    	// 创建订单数据
        OrderPayResponse orderPayResponse = new OrderPayResponse();
        StoreOrder storeOrder = super.createOrder(key, orderRequest, ip);
        orderPayResponse.setStatus("ADAPAY_DEGREE_PAY");
		orderPayResponse.addExtend("orderId",storeOrder.getOrderId());
        // 下单
		Map<String, Object> result = payPayment(storeOrder, ip, Constants.SERVICE_PAY_TYPE_ORDER);

        result.put("orderId", storeOrder.getOrderId());
        orderPayResponse.setResult(result);
		final Integer orderAutoId = orderRequest.getOrderAutoId();
		// 下单成功异步触发支付单申报
		if (Objects.equals(result.get("result"),"SUCCESS")){
			CompletableFuture.runAsync(()->{
				StoreOrder order = storeOrderService.getById(orderAutoId);
				List<StoreOrderInfo> list = storeOrderInfoService.list(Wrappers.<StoreOrderInfo>lambdaQuery().eq(StoreOrderInfo::getOrderId, orderAutoId));
				if (CollectionUtils.isEmpty(list)){
					return;
				}
				List<Integer> orderInfoIds = list.stream().map(StoreOrderInfo::getId).collect(Collectors.toList());
				String pushResult = "";
				try {
					Thread.sleep(30*1000);
					// TODO DIDIOK 支付22
					pushResult = storeOrderService.pushAdapayCustoms(orderInfoIds);
				}catch (Exception e){
					pushResult = e.getCause()+e.getMessage();
					log.error("自动推送支付单失败:",e);
				}
				DingTalkMsgUtil.sendMsg(DingMsgEnum.ORDER_PAY,String.format("支付单自动申报结果:%S,%s",order.getOrderId(),pushResult));
			});
		}
        return orderPayResponse;
    }
    
	/**
	 * 重新支付
	 */
    @Override
    public Map<String, Object> toPayOrder(StoreOrder order, String ip) {
        //支付调用请求
    	Map<String, Object> resultMap = new HashMap<>();
    	Map<String, Object> result = payPayment(order, ip, Constants.SERVICE_PAY_TYPE_ORDER);

    	resultMap.put("orderId", order.getOrderId());
    	resultMap.put("data", result);
    	resultMap.put("status", "ADAPAY_DEGREE_PAY");
        
        return resultMap;
    }
    
    /**
     * 退款
     */
    @Override
    public boolean refund(StoreOrderRefundRequest request, StoreOrder storeOrder, StoreOrderInfo storeOrderInfo) {
    	Integer merId = storeOrder.getMerId();
    	// 直接退款情况
        if(null == request.getAmount() || request.getAmount().compareTo(BigDecimal.ZERO)==0){
            return goOnRefund(request, storeOrder, storeOrderInfo);
        }
        // 退货退款情况, 先进行分账回退
//        if(1 == request.getType() && StringUtil.isNotBlank(storeOrder.getTransBackParam()) && MER_ID != merId) {
//        	JSONObject transBackParam = JSONObject.parseObject(storeOrder.getTransBackParam());
//        	String requestId = transBackParam.getString("requestId");
//        	String price = transBackParam.getString("ext1");
//        	
//        	boolean transDivRollbackStatus = transDivRollback(requestId, Constants.HF_USER_ID, price, merId);
//        	if(!transDivRollbackStatus) {
//        		throw new CrmebException("退款前分账回退失败! 请联系技术人员!");
//        	}
//        }
        
        // 回调地址
        String domain = systemConfigService.getValueByKeyException(WeChatConstants.DOMAIN);
        LocalDateTime time = LocalDateTime.now();
        // 基础参数
    	Map<String, String> sendParams = new HashMap<>();
		sendParams.put("inputCharset", CHARSET);
		sendParams.put("version", VERSION);
    	// 速云主体不分账
    	if(syMerIds.contains(merId)) {
			sendParams.put("merchantAcctId", MERCHANT_ACCT_ID_SY + "01");
			sendParams.put("terminalId", TERMINAL_ID_SY);
			// sendParams.put("terminalId", TERMINAL_ID_SY);
			sendParams.put("terminalId", TERMINAL_CUSTOMS_ID_SY);
			sendParams.put("memberCode", MERCHANT_ACCT_ID_SY);
		} else if (cpMerIds.contains(merId)){
    		sendParams.put("merchantAcctId", MERCHANT_ACCT_ID_CP + "01");
    		sendParams.put("terminalId", TERMINAL_ID_CP);
    		sendParams.put("memberCode", MERCHANT_ACCT_ID_CP);
    	} else if (ctMerIds.contains(merId)) {
			sendParams.put("merchantAcctId", MERCHANT_ACCT_ID_CT + "01");
			sendParams.put("terminalId", TERMINAL_ID_CT);
			sendParams.put("memberCode", MERCHANT_ACCT_ID_CT);
		} else if (msMerIds.contains(merId)) {
			sendParams.put("merchantAcctId", MERCHANT_ACCT_ID_MS + "01");
			sendParams.put("terminalId", TERMINAL_ID_MS);
			sendParams.put("memberCode", MERCHANT_ACCT_ID_MS);
		}
		sendParams.put("refundOrderId", storeOrder.getOrderId() + time.getHour() + "" + time.getMinute() + "" + time.getSecond()); // 商户退款订单号
		sendParams.put("originalOrderId", storeOrder.getOrderId()); // 商户原订单号
		sendParams.put("refundCurrency", CURRENCY); // 退款币种
		sendParams.put("refundAmount", request.getAmount().movePointRight(2).toString()); // 退款金额

    	// 是否有自建商品(不分账)
//    	String divFlag = "1";
//    	List<StoreOrderInfoVo> storeOrderInfoVos = storeOrderInfoService.getOrderListByOrderId(storeOrder.getId());
//    	for(StoreOrderInfoVo vo : storeOrderInfoVos) {
//    		int isEur = vo.getInfo().getProductInfo().getIsEurope();
//    		if(1 == isEur) {
//    			divFlag = "0";
//    			break;
//    		}
//    	}
//    	// 速云主体不分账
//    	if(MER_ID == merId) {
//    		divFlag = "0";
//    	}
//		sendParams.put("refundMode", divFlag); // 特殊退款
		// TODO DIDIOK 支付
		sendParams.put("bgUrl", domain + WeChatConstants.PAY_NOTIFY_API_URI_ADAPAY_DEGREE);
		sendParams.put("language", LANGUAGE);
		sendParams.put("signType", SIGN_TYPE);
		sendParams.put("submit", "Payment");
		sendParams.put("keyPass", password);
		sendParams.put("aliasName", alias);
		sendParams.put("ext1", Constants.SERVICE_PAY_TYPE_REFUND);
		sendParams.put("signMsg", refundSignTool(sendParams, merId));
		log.info("--------------- 汇付聚合支付退款原始数据: {}", JSON.toJSONString(sendParams));
		
		HttpSendResult payResult = simpleHttpsClient.postRequest(refundUrl, sendParams, 30000);
		log.info("--------------- 汇付聚合支付退款返回结果源数据: {}", JSON.toJSONString(payResult));

        // 结果处理(不代表实际退款成功)
		if(payResult.getStatus() != 200) {
			storeOrderStatusService.saveRefund(storeOrderInfo.getOrderId(), storeOrderInfo.getChildOrderNumber(), request.getAmount(), "失败,错误信息:"+ payResult.getStatus(), request.getType() == 1);
			return false;
		}
		String respTxt = payResult.getResponseBody();
		String refundResult = getRespParam(respTxt, "refundResult");
        if ("C0".equals(refundResult)) {
            return goOnRefund(request, storeOrder,storeOrderInfo);
        } else {
        	String msg = getRespParam(respTxt, "errorMsg");
			if (StringUtils.isBlank(msg)) {
				msg = getRespParam(respTxt, "errMsg");
			}
        	storeOrderStatusService.saveRefund(storeOrderInfo.getOrderId(),storeOrderInfo.getChildOrderNumber(), request.getAmount(), "失败,错误信息:" + msg, request.getType() == 1);
            throw new CrmebException(msg);
        }
    }

    /**
     * 购买会员
     */
    @Override
    public Object buyMember(BuyMemberRequest request) {
    	// 虚拟订单对象
        StoreOrder order = new StoreOrder();
        order.setMerId(request.getMerId());
        order.setOrderId(request.getOrderNo());
        order.setUid(request.getUid());
        order.setPayPrice(request.getPrice());
        order.setTotalNum(1);
    	
        //支付调用请求
    	Map<String, Object> resultMap = new HashMap<>();;
        Map<String, Object> result = payPayment(order, request.getClientIp(), Constants.SERVICE_PAY_TYPE_MEMBER);
        result.put("order_id",request.getOrderNo());
        resultMap.put("data", result);
        resultMap.put("status", "ADAPAY_DEGREE_PAY");
        
        return resultMap;
    }

	@Override
	public Map<String, Object> purchaseProduct(PurchaseProductRequest purchaseProductRequest, String ip) {
		// 虚拟订单
		StoreOrder storeOrder = new StoreOrder();
		storeOrder.setMerId(productTypeMerchantId);
		storeOrder.setOrderId(purchaseProductRequest.getOrderNo());
		storeOrder.setPayPrice(RoleEnum.getEnumByCode(purchaseProductRequest.getProductType()).getPrice());
		storeOrder.setTotalNum(1);
		storeOrder.setPayType(Constants.PAY_TYPE_WE_CHAT_NATIVE);

		// 支付调用请求
		Map<String, Object> resultMap = new HashMap<>();
		Map<String, Object> result = payPayment(storeOrder, ip, Constants.SERVICE_PAY_TYPE_PRODUCT);
		result.put("order_id", purchaseProductRequest.getOrderNo());
		resultMap.put("data", result);
		resultMap.put("status", "ADAPAY_DEGREE_PAY");

		return resultMap;
	}

	/**
     * 在线充值
     */
    @Override
    public Map<String, Object> rechage(UserRechargeRequest request) {
        request.setPayments(Constants.PAY_TYPE_ADAPAY_DEGREE);
        // 验证金额是否为最低金额
        BigDecimal rechargeMinAmount = new BigDecimal(systemConfigService.getValueByKeyException(Constants.CONFIG_KEY_RECHARGE_MIN_AMOUNT));
        if(0 < rechargeMinAmount.compareTo(request.getPrice())){
            throw new CrmebException("充值金额不能低于" + rechargeMinAmount);
        }
        // 获取充值模板
        if(request.getGroupDataId() > 0){
            SystemGroupDataRechargeConfigVo systemGroupData = systemGroupDataService.getNormalInfo(request.getGroupDataId(), SystemGroupDataRechargeConfigVo.class);
            if(null == systemGroupData){
                throw new CrmebException("您选择的充值方式已下架");
            }
            //售价和赠送
            request.setPrice(systemGroupData.getPrice());
            request.setGivePrice(BigDecimal.ZERO);
        }
        //生成系统订单
        request.setUserId(userService.getUserIdException());
        UserRecharge userRecharge = userRechargeService.create(request);

    	// 虚拟订单对象
        StoreOrder order = new StoreOrder();
        order.setMerId(request.getMerId());
        order.setOrderId(userRecharge.getOrderId());
        order.setUid(request.getUserId());
        order.setPayPrice(request.getPrice());
        order.setTotalNum(1);
        //支付调用请求
        Map<String, Object> resultMap = new HashMap<>();
    	Map<String, Object> result = payPayment(order, request.getClientIp(), Constants.SERVICE_PAY_TYPE_RECHARGE);
    	resultMap.put("orderId", order.getOrderId());
    	resultMap.put("data", result);
    	resultMap.put("status", "ADAPAY_DEGREE_PAY");
    	resultMap.put("type", request.getFromType());
        
        return resultMap;
    }

    /**
     * 二维码充值
     */
    @Override
    public UserRecharge createImgRecharge(BigDecimal price) {
        return null;
    }
    
    /**
     * 即时分账
     * @author daigb
     * @date:  2022-09-09 13:47
     */
    public JSONObject transDiv(String orderId, String payId, BigDecimal price, String hfUserId, Integer merId) {
        price = price.movePointRight(2).setScale(2, RoundingMode.UP);
    	String transPrice = price.toString();
    	
		Map<String, String> sendParams = new HashMap<String, String>();
		sendParams.put("inputCharset", CHARSET);
		sendParams.put("version", "1.0");
		sendParams.put("signType", SIGN_TYPE); // 加签类型
    	if(syMerIds.contains(merId)) {
    		sendParams.put("merchantAcctId", MERCHANT_ACCT_ID_SY + "01"); // 商户号
    		sendParams.put("terminalId", TERMINAL_ID_SY); // 终端号
    	} else if (cpMerIds.contains(merId)){
    		sendParams.put("merchantAcctId", MERCHANT_ACCT_ID_CP + "01"); // 商户号
    		sendParams.put("terminalId", TERMINAL_ID_CP); // 终端号
    	} else if (ctMerIds.contains(merId)) {
			sendParams.put("merchantAcctId", MERCHANT_ACCT_ID_CT + "01"); // 商户号
			sendParams.put("terminalId", TERMINAL_ID_CT); // 终端号
		} else if (msMerIds.contains(merId)) {
			sendParams.put("merchantAcctId", MERCHANT_ACCT_ID_MS + "01"); // 商户号
			sendParams.put("terminalId", TERMINAL_ID_MS); // 终端号
		}
		sendParams.put("requestId", orderId); // 请求流水号
		sendParams.put("requestTime", new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())); // 请求时间
		sendParams.put("dealId", payId); // 收单系统交易号，该交易在收单系统对应的交易号
		sendParams.put("details", hfUserId + "|" + transPrice + "|云仓分账"); // 分账明细
		sendParams.put("ext1", transPrice);
		sendParams.put("signMsg", transDivSignTool(sendParams, merId));

		HttpSendResult result = simpleHttpsClient.postRequest(transDivUrl, sendParams, 30000);
		log.info("--------------- 汇付聚合支付分账返回结果源数据: {}", JSON.toJSONString(result));
		
		return getRespParamJson(result.getResponseBody());
	}
    
    /**
     * 分账回退(金额单位: 分)
     * @author daigb
     * @date:  2022-09-23 11:01
     */
    public Boolean transDivRollback(String origReqId, String userId, String amount, Integer merId) {
//    	amount = amount.movePointRight(2).setScale(2, RoundingMode.UP);
//    	String transPrice = amount.toString();
    	
    	Map<String, String> sendParams = new HashMap<String, String>();
		sendParams.put("inputCharset", CHARSET);
		sendParams.put("version", "1.0");
		sendParams.put("signType", SIGN_TYPE); // 加签类型
    	if(syMerIds.contains(merId)) {
    		sendParams.put("merchantAcctId", MERCHANT_ACCT_ID_SY + "01"); // 商户号
    		sendParams.put("terminalId", TERMINAL_ID_SY); // 终端号
    	} else if (cpMerIds.contains(merId)){
    		sendParams.put("merchantAcctId", MERCHANT_ACCT_ID_CP + "01"); // 商户号
    		sendParams.put("terminalId", TERMINAL_ID_CP); // 终端号
    	} else if (ctMerIds.contains(merId)) {
			sendParams.put("merchantAcctId", MERCHANT_ACCT_ID_CT + "01"); // 商户号
			sendParams.put("terminalId", TERMINAL_ID_CT); // 终端号
		} else if (msMerIds.contains(merId)) {
			sendParams.put("merchantAcctId", MERCHANT_ACCT_ID_MS + "01"); // 商户号
			sendParams.put("terminalId", TERMINAL_ID_MS); // 终端号
		}
		sendParams.put("returnReqId", UUID.randomUUID().toString().replaceAll("-", "")); // 回退请求流水号, 不做记录
		sendParams.put("origReqId", origReqId); // 原请求流水号
		sendParams.put("userId", userId); // 用户id
		sendParams.put("amount", amount); // 单位分
		sendParams.put("requestTime", new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())); // 请求时间
		sendParams.put("ext1", "transDivRollback");
		sendParams.put("signMsg", transDivRollbackSignTool(sendParams, merId));

		HttpSendResult result = simpleHttpsClient.postRequest(rollbackUrl, sendParams, 30000);
		log.info("--------------- 汇付聚合支付分账回退返回结果源数据: {}", JSON.toJSONString(result));
		JSONObject resultObj = getRespParamJson(result.getResponseBody());
		
		return Constants.HTTPSTATUS_CODE_SUCCESS_STRING.equals(resultObj.getString("respCode"));
    }
    
    /**
	 * orderAmt=freightAmt+goodsAmt+taxAmt-offsetAmt
     * 支付单海关申报
     * @author daigb
     * @date:  2022-08-01 13:45
     */
    public HttpSendResult payCustoms(Integer merId, String realName, String idCard, String orderInfoId, String payId, BigDecimal orderAmt, BigDecimal freightAmt, BigDecimal goodsAmt, BigDecimal taxAmt, BigDecimal offsetAmt) {
        String domain = systemConfigService.getValueByKeyException(WeChatConstants.DOMAIN);
        
		Map<String, String> sendParams = new HashMap<String, String>();
		sendParams.put("version", "1.0");
		sendParams.put("signType", SIGN_TYPE); // 加签类型
		// TODO DIDIOK 支付
		sendParams.put("bgUrl", domain + WeChatConstants.PAY_NOTIFY_API_URI_ADAPAY_DEGREE); // 回调地址
		if (wmjMerIds.contains(merId)){
			sendParams.put("merchantAcctId", MERCHANT_ACCT_ID_SY + "01"); // 商户号
			sendParams.put("terminalId", TERMINAL_CUSTOMS_ID_WMJ); // 终端号
			sendParams.put("terminalId", "SYGYL006");
			sendParams.put("merCustomCode", "3303960EZ4"); // 商户海关备案号
			sendParams.put("merCustomName", "浙江速云供应链科技有限公司"); // 海关公司名
		}else if(syMerIds.contains(merId)) {
    		sendParams.put("merchantAcctId", MERCHANT_ACCT_ID_SY + "01"); // 商户号
    		sendParams.put("terminalId", TERMINAL_CUSTOMS_ID_SY); // 终端号
			sendParams.put("terminalId", "SYGYL006");
			sendParams.put("merCustomCode", "3303960EZ4"); // 商户海关备案号
			sendParams.put("merCustomName", "浙江速云供应链科技有限公司"); // 海关公司名
    	} else if (cpMerIds.contains(merId)){
    		sendParams.put("merchantAcctId", MERCHANT_ACCT_ID_CP + "01"); // 商户号
    		sendParams.put("terminalId", TERMINAL_CUSTOMS_ID_CP); // 终端号
			sendParams.put("terminalId", "SYGYL006");
			sendParams.put("merCustomCode", "3303960B04"); // 商户海关备案号
			sendParams.put("merCustomName", "温州诚品睿奢贸易有限公司"); // 海关公司名
    	} else if (ctMerIds.contains(merId)) {
			sendParams.put("merchantAcctId", MERCHANT_ACCT_ID_CT + "01"); // 商户号
			sendParams.put("terminalId", TERMINAL_CUSTOMS_ID_CT); // 终端号
			sendParams.put("terminalId", "SYGYL006");
			sendParams.put("merCustomCode", "3303960EZ4"); // 商户海关备案号
			sendParams.put("merCustomName", "浙江速云供应链科技有限公司"); // 海关公司名
		} else if (msMerIds.contains(merId)) {
			sendParams.put("merchantAcctId", MERCHANT_ACCT_ID_MS + "01"); // 商户号
			sendParams.put("terminalId", TERMINAL_CUSTOMS_ID_MS); // 终端号
			sendParams.put("terminalId", "SYGYL006");
			sendParams.put("merCustomCode", "3303960EZ4"); // 商户海关备案号
			sendParams.put("merCustomName", "浙江速云供应链科技有限公司"); // 海关公司名
		}
		sendParams.put("payerIdType", "1"); // 证件类型
		sendParams.put("payerName", realName);
		sendParams.put("payerIdNumber", idCard);		
		sendParams.put("customCode", "HZHG"); // 海关代码
		sendParams.put("customVersion", "1.0");
//		sendParams.put("merCustomCode", "3303960B04"); // 商户海关备案号
//		sendParams.put("merCustomName", "温州诚品睿奢贸易有限公司"); // 海关公司名
//		sendParams.put("merCustomCode", "3303960EZ4"); // 商户海关备案号
//		sendParams.put("merCustomName", "浙江速云供应链科技有限公司"); // 海关公司名
		sendParams.put("ecpShortName", "SHHF"); // 固定
		sendParams.put("ecpDomainName", "http://suyun999.com/");
		sendParams.put("competCustom", "1"); // 固定
		sendParams.put("iaqInstCode", "1"); // 固定		
		sendParams.put("orderId", orderInfoId);
		sendParams.put("dealId", payId);
		sendParams.put("orderCurrency", CURRENCY);
		sendParams.put("orderAmt", orderAmt.movePointRight(2).toString());
		sendParams.put("freightAmt", freightAmt.movePointRight(2).toString()); // 物流费
		sendParams.put("goodsAmt", goodsAmt.movePointRight(2).toString()); // 货款
		sendParams.put("taxAmt", taxAmt.movePointRight(2).toString()); // 税款
		sendParams.put("offsetAmt", offsetAmt.movePointRight(2).toString()); // 抵扣金额
		sendParams.put("ext1", "customs");
		sendParams.put("ext2", "");
		sendParams.put("signMsg", customsSignTool(sendParams, merId));
		log.info("--------------- 汇付聚合支付报关入参: {}", JSON.toJSONString(sendParams));
		HttpSendResult result = simpleHttpsClient.postRequest(customsUrl, sendParams, 30000);
		log.info("--------------- 汇付聚合支付报关返回结果源数据: {}", JSON.toJSONString(result));
		DingTalkMsgUtil.sendMsg(DingMsgEnum.OTHER,"汇付聚合支付报关返回结果:"+JSON.toJSONString(result));
		
		return result;
    }
    
    /******************************** 以下为工具方法 ******************************/
    /**
     * 支付下单真实请求
     * @author daigb
     * @date:  2022-07-18 16:01
     */
    private Map<String,Object> payPayment(StoreOrder order, String ip, String ex1) {
    	Integer merId = order.getMerId();
    	// 基础参数
    	Map<String, String> sendParams = getParams(merId);
    	// 是否扫码支付
    	boolean isNative = Constants.PAY_TYPE_WE_CHAT_NATIVE.equals(order.getPayType());
    	if(isNative) {
    		sendParams.put("deviceType", "1"); // PC端支付
    		sendParams.put("payType", "6"); // 聚合网关
    	} else {
			// 获取商户appId
			String appId = systemConfigService.getValueByKey("routine_appid_new_" + order.getMerId());
			if (StringUtils.isBlank(appId)){
				appId = systemConfigService.getValueByKeyException("routine_appid_" + order.getMerId());
			}
			JSONObject jsonObject = new JSONObject();
			jsonObject.put("appId", appId);
			// 指定appid上报，只允许deviceType=2，payType=7/8时有效
			sendParams.put("bizContent", jsonObject.toJSONString());
		}
    	// 是否有自建商品(不分账)
//    	String divFlag = "1";
//    	List<StoreOrderInfoVo> storeOrderInfoVos = storeOrderInfoService.getOrderListByOrderId(order.getId());
//    	for(StoreOrderInfoVo vo : storeOrderInfoVos) {
//    		int isEur = vo.getInfo().getProductInfo().getIsEurope();
//    		if(1 == isEur) {
//    			divFlag = "0";
//    			break;
//    		}
//    	}
//    	// 速云主体不分账
//    	if(MER_ID == merId) {
//    		divFlag = "0";
//    	}
//    	sendParams.put("divFlag", divFlag); // 分账标识
    	
    	// 身份信息
    	if(StringUtils.isNotBlank(order.getRealName())) {
    		sendParams.put("payerName", order.getRealName());
    	}
    	if(StringUtils.isNotBlank(order.getIdCard())) {
    		sendParams.put("payerIdentityCard", order.getIdCard());
    	}
		sendParams.put("orderId", order.getOrderId()); // 订单号
		sendParams.put("orderAmount", order.getPayPrice().movePointRight(2).toString()); // 订单金额(单位: 分)
		sendParams.put("productName", "自定义商品"); // 商品名称
		sendParams.put("productNum", null == order.getTotalNum() ? "1" : order.getTotalNum() + ""); // 商品数量
		sendParams.put("ext1", ex1); // 扩展字段1
		sendParams.put("ext2", ""); // 扩展字段2
		sendParams.put("customerIp", ip); // ip
		sendParams.put("signMsg", paySignTool(sendParams, merId));
		log.info("--------------- 汇付聚合支付下单原数据: {}", JSON.toJSONString(sendParams));

		HttpSendResult payResult = simpleHttpsClient.postRequest(payUrl, sendParams, 30000);
		log.info("--------------- 汇付聚合支付下单返回结果源数据: {}", JSON.toJSONString(payResult));

        // 海关清关原始参数保存
        storeOrderService.update(Wrappers.<StoreOrder>lambdaUpdate()
        		.set(StoreOrder :: getPayParam, JSON.toJSONString(sendParams))
        		.eq(StoreOrder :: getOrderId, order.getOrderId())
        		);

		// 下单结果
		Map<String, Object> result = new HashMap<>();
		String respTxt = payResult.getResponseBody();
		if (payResult.getStatus() == 200) {
			String payInfo = null;
			if (isNative) {
				payInfo = getRespParam(respTxt, "url");
				payInfo = URLDecoder.decode(payInfo);
			} else {
				payInfo = getRespParam(respTxt, "payInfo");
			}
			log.info("--------------- 汇付聚合支付payInfo数据: {}", payInfo);
			if(StringUtils.isBlank(payInfo)) {
				result.put("result", getRespParam(respTxt, "respMsg"));
				log.error("--------------- 汇付聚合支付下单其他失败!: {}", JSON.toJSONString(payResult));
			} else {
				if (!isNative) {
					JSONObject respInfo = JSONObject.parseObject(payInfo);
					result.put("pay_info", respInfo);
					result.put("result", "SUCCESS");
				} else {
					result.put("pay_info", payInfo);
					result.put("result", "SUCCESS");
				}

			}
		} else {
			result.put("result", getRespParam(respTxt, "respMsg"));
			log.error("--------------- 汇付聚合支付下单失败!: {}", JSON.toJSONString(payResult));
		}
		
		return result;
    }
    
    /**
     * 支付参数加签
     * @author daigb
     * @date:  2022-07-18 15:29
     */
    private String paySignTool(Map<String, String> sendParams, Integer merId) {
		String signMsgVal = "";
		signMsgVal = appendParam(signMsgVal, "pageUrl", sendParams.get("pageUrl").toString());
		signMsgVal = appendParam(signMsgVal, "bgUrl", sendParams.get("bgUrl").toString());
		signMsgVal = appendParam(signMsgVal, "merchantAcctId", sendParams.get("merchantAcctId").toString());
		signMsgVal = appendParam(signMsgVal, "terminalId", sendParams.get("terminalId").toString());
		signMsgVal = appendParam(signMsgVal, "orderId", sendParams.get("orderId").toString());
		signMsgVal = appendParam(signMsgVal, "orderAmount", sendParams.get("orderAmount").toString());
		signMsgVal = appendParam(signMsgVal, "orderTime", sendParams.get("orderTime").toString());
		signMsgVal = appendParam(signMsgVal, "ext1", sendParams.get("ext1").toString());
		signMsgVal = appendParam(signMsgVal, "ext2", sendParams.get("ext2").toString());
		signMsgVal = appendParam(signMsgVal, "deviceType", sendParams.get("deviceType").toString());
		signMsgVal = appendParam(signMsgVal, "payType", sendParams.get("payType").toString());

		return signMsg(signMsgVal, merId);
    }
    
    /**
     * 报关参数加签
     * @author daigb
     * @date:  2022-07-18 15:29
     */
    private String customsSignTool(Map<String, String> sendParams, Integer merId) {
    	String signMsgVal = "";
    	signMsgVal = appendParam(signMsgVal, "version", sendParams.get("version").toString());
    	signMsgVal = appendParam(signMsgVal, "bgUrl", sendParams.get("bgUrl").toString());
    	signMsgVal = appendParam(signMsgVal, "signType", sendParams.get("signType").toString());
    	signMsgVal = appendParam(signMsgVal, "merchantAcctId", sendParams.get("merchantAcctId").toString());
    	signMsgVal = appendParam(signMsgVal, "terminalId", sendParams.get("terminalId").toString());
    	signMsgVal = appendParam(signMsgVal, "dealId", sendParams.get("dealId").toString());
    	signMsgVal = appendParam(signMsgVal, "customCode", sendParams.get("customCode").toString());
    	signMsgVal = appendParam(signMsgVal, "customVersion", sendParams.get("customVersion").toString());
    	signMsgVal = appendParam(signMsgVal, "merCustomCode", sendParams.get("merCustomCode").toString());
    	signMsgVal = appendParam(signMsgVal, "merCustomName", sendParams.get("merCustomName").toString());
    	signMsgVal = appendParam(signMsgVal, "payerIdType", sendParams.get("payerIdType").toString());
    	signMsgVal = appendParam(signMsgVal, "payerName", sendParams.get("payerName").toString()); 
    	signMsgVal = appendParam(signMsgVal, "payerIdNumber", sendParams.get("payerIdNumber").toString());
    	signMsgVal = appendParam(signMsgVal, "orderId", sendParams.get("orderId").toString()); 
    	signMsgVal = appendParam(signMsgVal, "orderCurrency", sendParams.get("orderCurrency").toString());
    	signMsgVal = appendParam(signMsgVal, "orderAmt", sendParams.get("orderAmt").toString()); 
    	signMsgVal = appendParam(signMsgVal, "freightAmt", sendParams.get("freightAmt").toString());
    	signMsgVal = appendParam(signMsgVal, "goodsAmt", sendParams.get("goodsAmt").toString()); 
    	signMsgVal = appendParam(signMsgVal, "taxAmt", sendParams.get("taxAmt").toString());
    	signMsgVal = appendParam(signMsgVal, "offsetAmt", sendParams.get("offsetAmt").toString());

		return signMsg(signMsgVal, merId);
    }
    
    /**
     * 退款参数加签
     * @author daigb
     * @date:  2022-07-19 11:51
     */
    private String refundSignTool(Map<String, String> sendParams, Integer merId) {
    	String signMsgVal = "";
		signMsgVal = appendParam(signMsgVal, "inputCharset", sendParams.get("inputCharset").toString());
		signMsgVal = appendParam(signMsgVal, "bgUrl", sendParams.get("bgUrl").toString());
		signMsgVal = appendParam(signMsgVal, "version", sendParams.get("version").toString());
		signMsgVal = appendParam(signMsgVal, "language", sendParams.get("language").toString());
		signMsgVal = appendParam(signMsgVal, "signType", sendParams.get("signType").toString());
		signMsgVal = appendParam(signMsgVal, "merchantAcctId", sendParams.get("merchantAcctId").toString());
		signMsgVal = appendParam(signMsgVal, "terminalId", sendParams.get("terminalId").toString());
		signMsgVal = appendParam(signMsgVal, "refundOrderId", sendParams.get("refundOrderId").toString());
		signMsgVal = appendParam(signMsgVal, "originalOrderId", sendParams.get("originalOrderId").toString());
		signMsgVal = appendParam(signMsgVal, "refundCurrency", sendParams.get("refundCurrency").toString());
		signMsgVal = appendParam(signMsgVal, "refundAmount", sendParams.get("refundAmount").toString());
		signMsgVal = appendParam(signMsgVal, "ext1", sendParams.get("ext1").toString()); 

		return signMsg(signMsgVal, merId);
    }
    
    /**
     * 分账参数加签
     * @author daigb
     * @date:  2022-07-18 15:29
     */
    private String transDivSignTool(Map<String, String> sendParams, Integer merId) {
    	String signMsgVal = "";
		signMsgVal = appendParam(signMsgVal, "version", sendParams.get("version").toString());
		signMsgVal = appendParam(signMsgVal, "signType", sendParams.get("signType").toString());
		signMsgVal = appendParam(signMsgVal, "merchantAcctId", sendParams.get("merchantAcctId").toString());
		signMsgVal = appendParam(signMsgVal, "terminalId", sendParams.get("terminalId").toString());
		signMsgVal = appendParam(signMsgVal, "requestId", sendParams.get("requestId").toString());
		signMsgVal = appendParam(signMsgVal, "requestTime", sendParams.get("requestTime").toString());

		return signMsg(signMsgVal, merId);
    }
    
    /**
     * 分账回退参数加签
     * @author daigb
     * @date:  2022-07-18 15:29
     */
    private String transDivRollbackSignTool(Map<String, String> sendParams, Integer merId) {
    	String signMsgVal = "";
		signMsgVal = appendParam(signMsgVal, "version", sendParams.get("version").toString());
		signMsgVal = appendParam(signMsgVal, "signType", sendParams.get("signType").toString());
		signMsgVal = appendParam(signMsgVal, "merchantAcctId", sendParams.get("merchantAcctId").toString());
		signMsgVal = appendParam(signMsgVal, "terminalId", sendParams.get("terminalId").toString());
		signMsgVal = appendParam(signMsgVal, "returnReqId", sendParams.get("returnReqId").toString());
		signMsgVal = appendParam(signMsgVal, "origReqId", sendParams.get("origReqId").toString());
		signMsgVal = appendParam(signMsgVal, "userId", sendParams.get("userId").toString());
		signMsgVal = appendParam(signMsgVal, "requestTime", sendParams.get("requestTime").toString());

		return signMsg(signMsgVal, merId);
    }
    
    /**
     * 基础参数组装
     * @author daigb
     * @date:  2022-07-18 15:29
     */
    private Map<String, String> getParams(Integer merId) {
        // 回调地址
        String domain = systemConfigService.getValueByKeyException(WeChatConstants.DOMAIN);
        String domainUrl = systemConfigService.getValueByKeyException(WeChatConstants.DOMAIN_URL);

    	Map<String, String> sendParams = new HashMap<>();
		sendParams.put("inputCharset", CHARSET);
		sendParams.put("pageUrl", domainUrl + WeChatConstants.PAY_NOTIFY_API_URI_ADAPAY_DEGREE_PAGE);
		// TODO DIDIOK 支付
		sendParams.put("bgUrl", domain + WeChatConstants.PAY_NOTIFY_API_URI_ADAPAY_DEGREE);
		sendParams.put("version", VERSION);
		sendParams.put("language", LANGUAGE);
		sendParams.put("signType", SIGN_TYPE);
    	if(syMerIds.contains(merId)) {
    		sendParams.put("merchantAcctId", MERCHANT_ACCT_ID_SY + "01");
//    		sendParams.put("terminalId", TERMINAL_ID_SY); // 终端号
			sendParams.put("terminalId", TERMINAL_CUSTOMS_ID_SY);
    	} else if (cpMerIds.contains(merId)){
    		sendParams.put("merchantAcctId", MERCHANT_ACCT_ID_CP + "01");
    		sendParams.put("terminalId", TERMINAL_ID_CP); // 终端号
    	} else if (ctMerIds.contains(merId)) {
			sendParams.put("merchantAcctId", MERCHANT_ACCT_ID_CT + "01");
			sendParams.put("terminalId", TERMINAL_ID_CT); // 终端号
		} else if (msMerIds.contains(merId)) {
			sendParams.put("merchantAcctId", MERCHANT_ACCT_ID_MS + "01");
			sendParams.put("terminalId", TERMINAL_ID_MS); // 终端号
		}
		sendParams.put("payerContactType", "2");
		sendParams.put("orderCurrency", CURRENCY);
		sendParams.put("settlementCurrency", CURRENCY);
		sendParams.put("orderTime", sdf.format(new Date())); // 下单时间
		sendParams.put("openId", userService.getInfoToken()); // 下单用户openid
		sendParams.put("productId", "100200"); // 商品类目
		sendParams.put("deviceType", "2");
		sendParams.put("payType", "8");
		sendParams.put("redoFlag", "2");
		
		return sendParams;
    }
    
    private String signMsg(String signMsgVal, Integer merId) {
    	SignTool pki = new SignTool(MERCHANT_ACCT_ID_CP, PATH, password, alias);
    	if(syMerIds.contains(merId)) {
    		pki = new SignTool(MERCHANT_ACCT_ID_SY, PATH, password, alias);
    	} else if (cpMerIds.contains(merId)){
    		pki = new SignTool(MERCHANT_ACCT_ID_CP, PATH, password, alias);
    	} else if (ctMerIds.contains(merId)) {
			pki = new SignTool(MERCHANT_ACCT_ID_CT, PATH, password, alias);
		} else if (msMerIds.contains(merId)) {
			pki = new SignTool(MERCHANT_ACCT_ID_MS, PATH, password, alias);
		}
		return pki.signMsg(signMsgVal);
    }

    /**
     * 工具方法
     * @author daigb
     * @date:  2022-07-18 15:29
     */
    private static String appendParam(String returns, String paramId, String paramValue) {
		if (StringUtils.isNotBlank(returns)) {
			if (StringUtils.isNotBlank(paramValue)) {
				returns += "&" + paramId + "=" + paramValue;
			}
		} else {
			if (StringUtils.isNotBlank(paramValue)) {
				returns = paramId + "=" + paramValue;
			}
		}

		return returns;
	}
    
    /**
     * 工具方法
     * @author daigb
     * @date:  2022-07-18 15:29
     */
	public static String getRespParam(String respTxt, String targetKey) {
		String[] splipArr = respTxt.split("&");
		try {
			for (String sep : splipArr) {
				String[] entryArr = sep.split(targetKey + "=");
				if (entryArr.length > 1) {
					return entryArr[1];
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		return null;
	}
	
	/**
	 * 工具方法
	 * @author daigb
	 * @date:  2022-07-18 15:29
	 */
	public static JSONObject getRespParamJson(String respTxt) {
		JSONObject obj = new JSONObject();
		String[] splipArr = respTxt.split("&");
		try {
			for (String sep : splipArr) {
				String[] entryArr = sep.split("=");
				if (entryArr.length > 1) {
					obj.put(entryArr[0], entryArr[1]);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			
			return null;
		}
		
		return obj;
	}

}
